如果今天應用程式掛掉、導致服務無法提供使用者存取,希望 k8s 可以即時將服務重新 run 起來、使服務不被中斷,這時候就要提到 k8s 中的 ReplicaSet。
當應用程式的使用者增加時,需要提升服務的高可用性 (Hign Availability, HA)、提升負載平衡,或者是為了因應服務異常中斷,需要在環境中部署多個 instances,也就是多個 pods。
在 k8s 中可以用 ReplicaSet 來對 Pods 進行管理與監控。
ReplicaSet 是監控 pod 的一個程序,確保受到管理的 pods(應用服務都是放在 pod 中) 狀態為正常運行(running)。
ReplicaSet 主要的功能:
為達成 HA 及負載平衡,在叢集中通常會部署多個 pods。透過先前在 YAML 設定檔中的 labels 屬性以及待會將提到的 selector 屬性來指定 ReplicaSet 要管理哪些 pods。
透過幫 pods 貼標籤 labels,並在 ReplicaSet 上定義 selector 指定要管理哪些 pods。

圖片來源: https://velog.io/@gentledev10/kubernetes-replicaset
底下是一個用來建立應用程式的 pod 範例 nginx-pod.yaml。
apiVersion: v1
kind: Pod
metadata: nginx-pod
  name: nginx-pod
  labels:
    app: nginx-app
    tier: frontend
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
底下是一個 ReplicaSet 範例 nginx-rs.yaml,假設希望在叢集中維持執行 3 個 pods。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-app
  template:
    # 若是 pod 掛掉時,ReplicaSet 會按照以下內容來建立新的 pod
    metadata:
      name: nginx-pod
      labels:
        app: nginx-app
        tier: frontend
    spec:
      containers:
      - name: nginx-container
        image: nginx
        ports:
        - containerPort: 80
如同 pod 的定義一樣,有 apiVersion、kind、metadata 和 spec 屬性,不同的是在 spec 定義:
replicas:需要幾個 replica,這邊希望在叢集中跑三個 pods。selector:定義要管理的 labels 有哪些,在 matchLabels 下填上標籤 app 其值為 nginx-app,表示要連結至有此標籤的所有 pods。可以將不是由設定檔建立的 pod 也納入 replicaSet 的管理。template:pod 的詳細內容,其實就是把建立 pod 的設定檔底下的 metadata 及 spec 兩個屬性的內容原封不動搬過來。status:實際由 k8s 於執行時自動產生與更新,在定義時可不寫。執行 nginx-rs.yaml。
kubectl create -f nginx-rs.yaml
replicaset.apps/nginx-rs created
查看建立的 pods。
kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-dpghz   1/1     Running   0          106s
nginx-rs-nrw5r   1/1     Running   0          106s
nginx-rs-qpt2v   1/1     Running   0          106s
也可以用 label 篩選 pods,先建立一個沒有 label 的 pod。
kubectl run nginx --image=nginx
kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx            1/1     Running   0          37s
nginx-rs-dpghz   1/1     Running   0          3m33s
nginx-rs-nrw5r   1/1     Running   0          3m33s
nginx-rs-qpt2v   1/1     Running   0          3m33s
篩選 label 為 tier=frontend 的 pod。
kubectl get po -l tier=frontend
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-dpghz   1/1     Running   0          4m43s
nginx-rs-nrw5r   1/1     Running   0          4m43s
nginx-rs-qpt2v   1/1     Running   0          4m43s
加上 -o wide 可以看到 ReplicaSet 的 selector 為 app=nginx-app。
kubectl get replicaset nginx-rs -o wide
NAME       DESIRED   CURRENT   READY   AGE     CONTAINERS        IMAGES   SELECTOR
nginx-rs   3         3         3       6m13s   nginx-container   nginx    app=nginx-app
刪掉 nginx pod。
kubectl delete po nginx
pod "nginx" deleted
查看該 ReplicaSet 的詳細資料。
kubectl describe replicaset nginx-rs
Name:         nginx-rs
Namespace:    default
Selector:     app=nginx-app
Labels:       <none>
Annotations:  <none>
Replicas:     3 current / 3 desired
Pods Status:  3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx-app
           tier=frontend
  Containers:
   nginx-container:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  7m22s  replicaset-controller  Created pod: nginx-rs-nrw5r
  Normal  SuccessfulCreate  7m22s  replicaset-controller  Created pod: nginx-rs-dpghz
  Normal  SuccessfulCreate  7m22s  replicaset-controller  Created pod: nginx-rs-qpt2v
觀察 selector、labels、Replicas、Pods Status 和底下的 Events(建立 pod 的事件紀錄)。
若想要修改 ReplicaSet,例如把其中的 replicas 修改為其他數量,有三種修改方式:
nginx-rs.yaml 內的內容kubectl scale 指令kubectl edit 指令先來看第 1 種直接修改 nginx-rs.yaml。
kubectl replace -f nginx-rs.yaml
replicaset.apps/nginx-rs replaced
修改其中的 replicas 為 2。
vi nginx-rs.yaml
查看 ReplicaSet。
kubectl get rs nginx-rs
NAME       DESIRED   CURRENT   READY   AGE
nginx-rs   2         2         2       6m4s
查看 pods running 變為 2 個。
kubectl get po
NAME             READY   STATUS    RESTARTS   AGE
nginx-rs-jcq5h   1/1     Running   0          6m42s
nginx-rs-whmw6   1/1     Running   0          6m42s
第 2 種使用 scale 設定 replicas 為 6。
kubectl scale replicaset nginx-rs --replicas=6
replicaset.apps/nginx-rs scaled
查看當前 ReplicaSet。
kubectl get rs nginx-rs
NAME       DESIRED   CURRENT   READY   AGE
nginx-rs   6         6         6       18m
查看 pods running 變為 6 個。
kubectl get po -o wide
NAME             READY   STATUS    RESTARTS   AGE    IP            NODE       NOMINATED NODE   READINESS GATES
nginx-rs-6825z   1/1     Running   0          2m4s   10.244.0.15   minikube   <none>           <none>
nginx-rs-dpghz   1/1     Running   0          19m    10.244.0.11   minikube   <none>           <none>
nginx-rs-g94bm   1/1     Running   0          2m4s   10.244.0.13   minikube   <none>           <none>
nginx-rs-l2zp5   1/1     Running   0          2m4s   10.244.0.14   minikube   <none>           <none>
nginx-rs-nrw5r   1/1     Running   0          19m    10.244.0.10   minikube   <none>           <none>
nginx-rs-qpt2v   1/1     Running   0          19m    10.244.0.9    minikube   <none>           <none>
第 3 種是使用 edit,把 replicas 改回 3。
# k8s 會提供一個暫時的 file 可以修改,若儲存後則 apply 這個版本的 replicaset
kubectl edit replicaset nginx-rs
replicaset.apps/nginx-rs edited
查看當前 ReplicaSet 跟 pods,scale down 後變為 3。
kubectl get rs,po
NAME                       DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-rs   3         3         3       27m
NAME                 READY   STATUS    RESTARTS   AGE
pod/nginx-rs-dpghz   1/1     Running   0          27m
pod/nginx-rs-nrw5r   1/1     Running   0          27m
pod/nginx-rs-qpt2v   1/1     Running   0          27m
注意:使用第 2 種(
kubectl scale)與第 3 種(kubectl edit)方式並不會自動修改nginx-rs.yaml設定檔裡的內容,下次再執行時replicas依然是原本的 3。
同時刪除所有在設定檔中建立與管理的 pods,也就是 labels 有對應到的 pods。
kubectl delete replicaset nginx-rs
replicaset.apps "nginx-rs" deleted 
查看 ReplicaSet。
kubectl get replicaset
No resources found in default namespace.
status 屬性是由 k8s 自動產生與變動的,在執行 kubectl create -f nginx-rs.yaml 或異動 ReplicaSet 後,k8s 會去 etcd 取得叢集中 status 的資料,並比對當前叢集的狀態、設定檔中的狀態有沒有一致。
例如修改 nginx-rs.yaml 的 replicas 為 2。
vi nginx-rs.yaml
kubectl replace -f nginx-rs.yaml
replicaset.apps/nginx-rs replaced
可以透過 kubectl edit 來觀察。
kubectl edit replicaset nginx-rs
# 省略部分 ...
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx-app
        tier: frontend
      name: nginx-pod
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx-container
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 2
  fullyLabeledReplicas: 2
  observedGeneration: 2
  readyReplicas: 2
  replicas: 2
如上可以看到 status 屬性。